package protocol

import (
	"bytes"
	"encoding/binary"
	"io"
	"net"
	"sync"
)

type IReadWrite interface {
	ReadAll(r io.Reader, buf []byte) (n int, err error)
	WriteALL(w io.Writer, data []byte) bool
}

type EprotocolDataType uint8

const (
	PDT_binary EprotocolDataType = iota + 1
	PDT_msgpack
	PDT_bson
	PDT_json
	PDT_xml
	PDT_protobuf
)

type EprotocolCryptType uint8

const (
	ECT_NoneCrypt EprotocolCryptType = iota + 1 //没有加密
	ECT_AES
	ECT_RSA
	ECT_Custom
)

var HeadSize = 18

var ConnLists sync.Map

type TConnInfo struct {
	Protocol *ProtocolBase
}

type TprotocolHead struct {
	Magic      [4]uint8           //协议头标识
	Version    uint16             //协议版本号
	DataType   EprotocolDataType  //实际数据类型
	CryptType  EprotocolCryptType //加密类型
	DataLen    uint32             //实际数据长度
	ExtendHead uint16             //扩展头长度
	checksum   uint32             //校验码 //加密前的校验码，接收端需解密后做对比
}

type Metadata struct {
	Head       TprotocolHead //头
	ExtendData []uint8       //扩展数据
	Data       []uint8       //实际数据
}

type TconnTmpDataObj struct {
	//用于接收协议头，协议头的长度是已经知道的sizeof(TprotocolHead)
	RecvHead TprotocolHead
	//用于接收扩展头，扩展头的长度在协议头中
	RecvExtendData []uint8 //接收的扩展头数据
	//用于接收数据
	RecvData []uint8 //接收数据缓冲区，单个完整的包数据

	//用于发送协议头
	SendHeadData TprotocolHead
	//用于发送扩展头，扩展头的长度在协议头中
	SendExtendData []uint8 //发送的扩展头数据
	//用于发送数据
	SendData []uint8 //发送数据缓冲区，单个完整的包数据
}

type HandleExtendHead func([]uint8)

type ProtocolBase struct {
	ConnIndex    uint64
	Conn         net.Conn
	ConnData     TconnTmpDataObj
	OnExtendHead HandleExtendHead

	RecvQ     chan Metadata
	SendQ     chan Metadata
	CloseChan chan struct{}
	Locker    sync.Mutex
}

func (this *ProtocolBase) resetRecvRequest() {
	this.ConnData.RecvHead = TprotocolHead{}
}

func (this *ProtocolBase) Exit() {
	this.CloseChan <- struct{}{}
}

func (this *ProtocolBase) InitClient(avConn net.Conn, avConnIndex uint64) {
	this.RecvQ = make(chan Metadata, 2000)
	this.SendQ = make(chan Metadata, 2000)
	this.CloseChan = make(chan struct{})
	this.Conn = avConn
	this.ConnIndex = avConnIndex
}

func (this *ProtocolBase) WriteALL(w io.Writer, data []byte) bool {
	println("parent WriteALL!")
	return true
}

func (this *ProtocolBase) ReadAll(r io.Reader, buf []byte) (n int, err error) {
	println("parent ReadAll!")
	return 0, nil
}

func (this *ProtocolBase) ReadHead(avReadWrite IReadWrite) bool {
	headData := make([]uint8, HeadSize)
	lvReadLen, err := avReadWrite.ReadAll(this.Conn, headData)
	if err != nil {
		return false
	}
	if lvReadLen == 0 {
		return false
	}
	headReader := bytes.NewBuffer(headData)
	err = binary.Read(headReader, binary.LittleEndian, &this.ConnData.RecvHead)
	if err != nil {
		return false
	}
	return true
}

func (this *ProtocolBase) sendHead(avReadWrite IReadWrite) bool {
	headData := make([]uint8, HeadSize)
	headWrite := bytes.NewBuffer(headData)
	err := binary.Write(headWrite, binary.LittleEndian, &this.ConnData.SendHeadData)
	if err != nil {
		return false
	}
	return avReadWrite.WriteALL(this.Conn, headData)
}

func (this *ProtocolBase) ProcessRecvData(avReadWrite IReadWrite) bool {
	if !this.ReadHead(avReadWrite) {
		return false
	}

	if this.ConnData.RecvHead.ExtendHead > 0 {
		this.ConnData.RecvExtendData = make([]uint8, this.ConnData.RecvHead.ExtendHead)
		_, err := this.ReadAll(this.Conn, this.ConnData.RecvExtendData)
		if err != nil {
			return false
		}
		if this.OnExtendHead != nil {
			this.OnExtendHead(this.ConnData.RecvExtendData)
		}
	}

	if this.ConnData.RecvHead.DataLen > 0 {
		this.ConnData.RecvData = make([]uint8, this.ConnData.RecvHead.DataLen)
		_, err := this.ReadAll(this.Conn, this.ConnData.RecvData)
		if err != nil {
			return false
		}
	}

	return true
}

func (this *ProtocolBase) ProcessSendData(avReadWrite IReadWrite) bool {
	if !this.sendHead(avReadWrite) {
		return false
	}
	if this.ConnData.SendHeadData.ExtendHead > 0 {
		if !avReadWrite.WriteALL(this.Conn, this.ConnData.SendExtendData) {
			return false
		}
	}
	if this.ConnData.SendHeadData.DataLen > 0 {
		if !avReadWrite.WriteALL(this.Conn, this.ConnData.SendData) {
			return false
		}
	}

	return true
}
